package com.epoch.platform.common.util;

import com.alibaba.fastjson.JSON;
import com.epoch.base.constant.Constant;
import com.epoch.base.util.GlobelConstant;
import com.epoch.platform.common.dao.SysAttachmentFiles;
import com.epoch.platform.common.service.CommonAttachService;
import com.epoch.platform.common.vo.AttachInfoDto;
import com.epoch.platform.common.vo.SaveAttachDto;
import com.jfinal.kit.PropKit;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;

public class CommonAttachUtils {
    private static final transient Logger LOG = LoggerFactory.getLogger(CommonAttachUtils.class);
    private static final CommonAttachUtils OBJ = new CommonAttachUtils();
    private CommonAttachService service = new CommonAttachService();

    /**
     * 获取系统附件归档根目录(由系统配置文件中读取)
     *
     * @return 系统附件归档根目录
     */
    public static String getAttachBasePath() {
        return PropKit.use(Constant.EPOCH_INIT).get(CommonAttachConstant.PROP_ATTACHBASEPATH);
    }

    /**
     * 由上传文件名获取文件fileKey字符串，此fileKey用于页面下载等功能引用后台文件对象
     *
     * @param fileName 指定文件名
     * @return 指定文件生成的fileKey
     */
    public static String getFileKeyFromFileName(String fileName) {
        String fileKey = null;
        if (fileName != null) {
            try {
                String encName = URLEncoder.encode(fileName, GlobelConstant.UTF8);
                fileKey = CommonAttachConstant.FILE_KEY_PRE + encName;
            } catch (UnsupportedEncodingException e) {
                CommonAttachUtils.LOG.error("encode file name '" + fileName + "' failed.", e);
            }
        }
        return fileKey;
    }

    /**
     * 由上传文件fileKey获取文件名
     *
     * @param fileKey 指定文件fileKey
     * @return 由fileKey中提取出的实际文件名
     */
    public static String getFileNameFromFileKey(String fileKey) {
        String fileName = null;
        if (fileKey != null) {
            String encName = fileKey.substring(CommonAttachConstant.FILE_KEY_PRE.length());
            try {
                fileName = URLDecoder.decode(encName, GlobelConstant.UTF8);
            } catch (UnsupportedEncodingException e) {
                CommonAttachUtils.LOG.error("decode file name '" + encName + "' failed.", e);
            }
        }
        return fileName;
    }

    /**
     * 将commonAttach组件提交的附件JSON转换为上传文件对象
     *
     * @param attachJson 附件JSON字符串
     * @return 转换后的上传文件对象，可用于获取上传文件的相关数据
     */
    public static SaveAttachDto parseAttachJson(String attachJson) {
        SaveAttachDto dto = null;
        if (StringUtils.isNotEmpty(attachJson)) {
            try {
                dto = JSON.parseObject(attachJson, SaveAttachDto.class);
            } catch (RuntimeException e) {
                CommonAttachUtils.LOG.error("failed to parse upload attachments JSON '" + attachJson + "'", e);
            }
        }
        return dto;
    }

    /**
     * 根据上传文件的fileKey获取文件路径(注意此fileKey必须是临时上传的文件fileKey，对于已存档文件请调用obtainAttachFilePath方法)
     *
     * @param fileKey 指定上传文件fileKey
     * @return 实际文件路径
     */
    public static String obtainUploadFilePath(String fileKey) {
        String filePath = null;
        if (StringUtils.isNotEmpty(fileKey)) {
            String fileName = CommonAttachUtils.getFileNameFromFileKey(fileKey);
            if (fileName != null) {
//                String webRoot = PathKit.getWebRootPath();
//                String baseUploadPath = JFinal.me().getConstants().getBaseUploadPath();
//                filePath = webRoot + File.separator + baseUploadPath + File.separator + fileName;
                  filePath = getFileNameExt(fileName, false);
            }
        }
        return filePath;
    }

    /**
     * 根据上传文件对象AttachInfoDto获取实际文件路径(注意此AttachInfoDto必须是临时上传的文件对象封装，对于已存档文件请调用obtainAttachFilePath方法)
     *
     * @param attachInfo 指定上传文件对象
     * @return 实际文件路径
     */
    public static String obtainUploadFilePath(AttachInfoDto attachInfo) {
        String filePath = null;
        if (attachInfo != null) {
            filePath = CommonAttachUtils.obtainUploadFilePath(attachInfo.getFileKey());
        }
        return filePath;
    }

    /**
     * 根据附件文件的fileKey获取文件路径(注意此fileKey必须是已存档的文件fileKey(附件文件ID)，对于临时上传文件请调用obtainUploadFilePath方法)
     *
     * @param fileKey 指定附件文件fileKey(附件文件ID)
     * @return 实际文件路径
     */
    public static String obtainAttachFilePath(String fileKey) {
        return CommonAttachUtils.OBJ.doObtainAttachFilePath(fileKey);
    }

    /**
     * 根据附件文件对象AttachInfoDto获取实际文件路径(注意此AttachInfoDto必须是已存档的文件对象封装，对于临时上传文件请调用obtainUploadFile方法)
     *
     * @param attachInfo 指定附件文件对象
     * @return 实际文件路径
     */
    public static String obtainAttachFilePath(AttachInfoDto attachInfo) {
        String filePath = null;
        if (attachInfo != null) {
            filePath = CommonAttachUtils.obtainAttachFilePath(attachInfo.getFileKey());
        }
        return filePath;
    }

    /**
     * 根据附件文件实体SysAttachmentFiles获取实际文件路径
     *
     * @param attachFile 指定附件文件实体
     * @return 实际文件路径
     */
    public static String obtainAttachFilePath(SysAttachmentFiles attachFile) {
        String filePath = null;
        if (attachFile != null) {
            String fileServerPath = attachFile.getStr(SysAttachmentFiles.SERVER_UPLOAD_PATH);
            if (StringUtils.isNotEmpty(fileServerPath)) {
                filePath = CommonAttachUtils.getAttachBasePath() + fileServerPath;
            }
        }
        return filePath;
    }

    private String doObtainAttachFilePath(String fileKey) {
        String filePath = null;
        if (StringUtils.isNotEmpty(fileKey)) {
            try {
                SysAttachmentFiles attach = this.service.getByPk(fileKey);
                filePath = CommonAttachUtils.obtainAttachFilePath(attach);
            } catch (NumberFormatException e) {
                CommonAttachUtils.LOG.error("invalid attachment file key(attachment_file_id) '" + fileKey + "'", e);
            }
        }
        return filePath;
    }

    public static String getAttachmentTempBasePath() {
        return PropKit.use(Constant.EPOCH_INIT).get("config.attachment.temp.basePath");
    }

    public static void copyFile(File srcFile, File destFile) throws IOException {
        if (null != destFile) {
            if (!destFile.getParentFile().isDirectory()) {
                destFile.getParentFile().mkdir();
            }
            try {
                FileUtils.copyFile(srcFile, destFile);
            } catch (IOException e) {
                LOG.error("-##copyFile is error,srcFile:{} destFile:{} ,errorMsg:{}", srcFile.getPath(), destFile.getPath(), e.getMessage());
                throw e;
            }
        }
    }

    public static String getFileNameExt(String fileName, boolean isTimestamp) {
        return CommonAttachUtils.getAttachmentTempBasePath() + File.separator + (isTimestamp ? System.currentTimeMillis() : Constant.STR_EMPTY) + fileName;
    }

    private CommonAttachUtils() {
        // 禁止工具类实例化
    }
}
